package leetcode;

import java.util.HashMap;
import java.util.Map;

/**
 * 137. 只出现一次的数字 II
 * 给你一个整数数组 nums ，除某个元素仅出现 一次 外，其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。
 * <p>
 * <p>
 * <p>
 * 示例 1：
 * <p>
 * 输入：nums = [2,2,3,2]
 * 输出：3
 * 示例 2：
 * <p>
 * 输入：nums = [0,1,0,1,0,1,99]
 * 输出：99
 */
public class SingleNumber2 {

    /**
     * 没看懂 推荐
     *
     * @param nums
     * @return
     */
    public int singleNumber(int[] nums) {

        int ones = 0, twos = 0;
        for (int num : nums) {
            ones = ones ^ num & ~twos;
            twos = twos ^ num & ~ones;
        }
        return ones;
    }


    /**
     * 二进制的每一位相加，与3取余，剩余的二进制就是
     *
     * @param nums
     * @return
     */
    public int singleNumber2(int[] nums) {
        //最终的结果值
        int ans = 0;
        //int类型有32位，统计每一位1的个数
        for (int i = 0; i < 32; i++) {
            //统计第i位中1的个数
            int oneCount = 0;
            for (int j = 0; j < nums.length; j++) {
                // 第 j 个数的 第 i位 二进制 是否为 1
                int cur = nums[j];
                // 二进制往右移动i位，与上1，如果是1则返回1，如果是0则返回0
                int isOne = (cur >> i) & 1;
                oneCount = oneCount + isOne;
            }
            //如果1的个数不是3的倍数，说明那个只出现一次的数字的二进制位中在这一位是1
            if (oneCount % 3 == 1){
                // 把 100000（i个0） 与 ans 进行或操作。
                ans = ans | (1 << i);
            }
        }
        return ans;
    }


    /**
     * 空间复杂度高 不推荐
     *
     * @param nums
     * @return
     */
    public int singleNumber1(int[] nums) {
        Map<Integer, Integer> freq = new HashMap<Integer, Integer>();
        for (int num : nums) {
            freq.put(num, freq.getOrDefault(num, 0) + 1);
        }
        int ans = 0;
        for (Map.Entry<Integer, Integer> entry : freq.entrySet()) {
            int num = entry.getKey(), occ = entry.getValue();
            if (occ == 1) {
                ans = num;
                break;
            }
        }
        return ans;
    }


}
